grammar LogoTurtle;

options{
	language = Java;
	output=AST;
	ASTLabelType=CommonTree;
}

tokens {BLOCK; }


prog	:	stat+ -> ^(BLOCK stat+) ;

stat	:	(print | make | ifstat | whilestat | ifelse | funcmake| funcreturn | COMMENT! | NEWLINE! | WS! ) endstat!
	|	(PENUP | PENDOWN | turtone | turtpos | turtcirc | turtpenc | BFILL | EFILL ) endstat!
	;
	
turtpos	:	SETPOS^ '['! expr expr ']'!
	;
	
turtcirc	:	CIRCLE^ expr expr
	;
	
turtpenc	:	SETPEN^ '['! expr expr expr ']'!
	;
		
turtone	:	(FORWARD | BACKWARD | LEFT | RIGHT | SETH)^ expr
	;
	
ifstat	:	IFSTAT compare block -> ^(IFSTAT compare block)
	;
	
whilestat	:	WHILESTAT '[' compare ']' block  -> ^(WHILESTAT compare block)
	;

ifelse	:	IFELSE compare block block -> ^(IFELSE compare block block)
	;
	
	
block	:	'['! stat+ ']'! 
	;	
	
	
print	:	PRINT expr -> ^(PRINT expr+)
	|	'(' PRINT expr+ ')' -> ^(PRINT expr+)
	;
	
funcmake	:	TO funcbody END -> ^(TO funcbody)
	;
	
funcbody	:	ID '(' expr+ ')' endstat stat+ -> ^( ID expr+ stat+ )
	;
	
funccall	:	ID^ '('! expr+ ')'!
	;
	
number	:	FLOAT | INT;

	
make	:	MAKE var expr -> ^(MAKE var expr)
	;
	
funcreturn	:	OUTPUT expr -> ^(OUTPUT expr)
	;
		 
var	:	REFOP  ID -> ^(REFOP ID)
	;

compare	:	expr COMPOP expr -> ^(COMPOP expr+)
	|	NOT compare -> ^(NOT compare)
	;
	
endstat	:	COMMENT*NEWLINE*WS*
	;

expr	:	multExpr ((ADD^|SUB^) multExpr)*
	;
	
multExpr	:	atom((DIV^|MUL^) atom)*
	|	MOD atom atom -> ^(MOD atom atom)
	;
	
atom	:	var
	|	number
	|	funccall
	|	'('! expr ')'!
	;

//TOKEN	:	COMMAND | ID | NUMBER | MATHOP | REFOP | NEWLINE | WS;
COMMENT	 :	';' (('!'..'~')|WS)*;

IFELSE	:	'ifelse';

PENDOWN	:	'pendown'|'pd';

PENUP	:	'penup'|'pu';

FORWARD	:	'forward'|'fd';

BACKWARD	:	'back'|'bk';

LEFT	:	'left'|'lt';

RIGHT	:	'right'|'rt';

SETH	:	'setheading'|'seth';

SETPOS	:	'setpos';

CIRCLE	:	'circle';

SETPEN	:	'setpencolor';

BFILL	:	'beginfill';

EFILL	:	'endfill';

PRINT	:	'print';

MAKE	:	'make';

WHILESTAT	:	'while';

IFSTAT	:	'if';	

MOD	:	'modulo';

TO	:	'to' ;

NOT	:	'not' ;

OUTPUT	:	'output';

END	:	'end';

		
ID	:	('_')*LETTER(LETTER|DIGIT|'_')* ;

INT	:	DIGIT+ ;

FLOAT	:	DIGIT+ '.' DIGIT+;

ADD	:	'+';

SUB	:	'-';

MUL	:	'*';

DIV	:	'/';

COMPOP	:	'>'|'<'|'>='|'<='|'+'|'=';	

REFOP	:	'"'|':' ;

NEWLINE	:	'\n'|'\r' {$channel = HIDDEN;} ;

WS	:	(' '| '\t') {$channel = HIDDEN;};

fragment LETTER 
	:	('a'..'z')|('A'..'Z');	

fragment DIGIT
	:	'0'..'9';		
